package com.douding.file.controller.admin;

import com.douding.server.domain.Test;
import com.douding.server.dto.FileDto;
import com.douding.server.dto.ResponseDto;
import com.douding.server.enums.FileUseEnum;
import com.douding.server.service.FileService;
import com.douding.server.service.TestService;
import com.douding.server.util.Base64ToMultipartFile;
import com.douding.server.util.UuidUtil;
import com.douding.server.util.ValidatorUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

/*
    返回json 应用@RestController
    返回页面  用用@Controller
 */
@RequestMapping("/admin/file")
@RestController
public class UploadController {

    private static final Logger LOG = LoggerFactory.getLogger(UploadController.class);
    public  static final String BUSINESS_NAME ="文件上传";
    @Resource
    private TestService testService;

    @Value("${file.path}")
    private String FILE_PATH;

    @Value("${file.domain}")
    private String FILE_DOMAIN;

    @Resource
    private FileService fileService;

    @RequestMapping("/upload")
    public ResponseDto upload(@RequestBody FileDto fileDto) throws Exception {
        //获取文件编码信息
        String base64Code = fileDto.getShard();

        //转换成MultipartFile
        MultipartFile multipartFile = Base64ToMultipartFile.base64ToMultipart(base64Code);

        //用途
        String name = FileUseEnum.getByCode(fileDto.getUse()).name().toLowerCase();

        //创建文件夹    /Users/xiaozhe/Downloads/td/teacher
        File file = new File(FILE_PATH + name);
        if (!file.exists()){
            //如果不存在则先创建
            file.mkdirs();
        }

        //相对文件（等会放在数据库中）    teacher/FGHufhWFI.png
        String relationPath = name + "/" + fileDto.getKey() + "." + fileDto.getSuffix();

        //分片文件（等会合并） /Users/xiaozhe/Downloads/td/Teacher/FGHuDfhWFI.png.1/2/3/4
        String splitFile= FILE_PATH + relationPath + "." + fileDto.getShardIndex();

        fileDto.setPath(relationPath);
        //分片保存到数据库中
        fileService.save(fileDto);
        fileDto.setPath(FILE_DOMAIN + relationPath);

        ResponseDto<FileDto> responseDto=new ResponseDto<>();
        responseDto.setContent(fileDto);

        //将分片文件写入写入
        try {
            LOG.info("写入中，字节大小："+(fileDto.getShardSize() >> 10) +"KiB");
            //判断是否需要直接写入文件,如果总的分片大小为1则说明不需要分片合并
            if (fileDto.getShardTotal() == 1){
                multipartFile.transferTo(new File(FILE_PATH+relationPath));
                return responseDto;//直接返回
            }else {
                multipartFile.transferTo(new File(splitFile));
            }
        } catch (IOException e) {
            LOG.info("=========写入失败=========");
            e.printStackTrace();
        }

        Integer shardIndex = fileDto.getShardIndex();
        Integer shardTotal = fileDto.getShardTotal();
        //判断是否所有分片上传完，要不要合并
        if (shardTotal.equals(shardIndex)){
            merge(fileDto);
        }

        return responseDto;
    }

    //合并分片
    public void merge(FileDto fileDto) {
        LOG.info("=========合并分片开始=========");

        //  teacher/FGHuEfhWFI.png
        String pathFile = fileDto.getPath();

        //真正要保存的文件地址
        String realFile = FILE_PATH + pathFile;

        try {
            // 创建一个输出文件流,用于写入合并后的文件
            FileOutputStream outputStream = new FileOutputStream(realFile);

            byte[] buffer = new byte[fileDto.getSize()];
            for (int i = 1; i <= fileDto.getShardTotal(); i++) {
                // 创建一个输入流，用于读取文件内容
                FileInputStream fileInputStream = new FileInputStream(realFile + "." + i);
                //从输入流里面读出内容并写入缓存区里面，最后再写入输出流
                int length=0;
                while ((length = fileInputStream.read(buffer)) > 0){
                    outputStream.write(buffer,0,length);
                }
                fileInputStream.close();
            }
            outputStream.close();
            LOG.info("=========文件合并成功=========");
        } catch (IOException e) {
            e.printStackTrace();
            LOG.info("=========文件合并失败=========");
        }

        //删除分片
        for (int i = 1; i <= fileDto.getShardTotal(); i++) {
            String deleteFile = realFile + "." + i;
            File file = new File(deleteFile);
            file.delete();
        }

    }

    @GetMapping("/check/{key}")
    public ResponseDto check(@PathVariable String key) throws Exception {
            ValidatorUtil.require(key,"key");
        LOG.info("检查上传分片开始：{}", key);
        FileDto fileDto = fileService.findByKey(key);
        ResponseDto<FileDto> responseDto = new ResponseDto();

        if (fileDto != null) {
            fileDto.setPath(FILE_DOMAIN + "/" + fileDto.getPath());
            responseDto.setContent(fileDto);
        }

        return responseDto;
    }

}//end class
